﻿//using Newtonsoft.Json;
using BaseUtils.Logger;
using BaseUtils.Utils;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using System;
using System.ComponentModel;
using System.Reflection;
using System.Text.RegularExpressions;

namespace BaseUtils.Helper
{
    public static class ConvertHelper
    {
        public static double TryToDouble(this string val)
        {
            try
            {
                return Convert.ToDouble(val);
            }
            catch
            {
                return 0;
            }
        }

        public static float TryToFloat(this string val)
        {
            try
            {
                return Convert.ToSingle(val);
            }
            catch
            {
                return 0;
            }
        }

        public static int TryToInt32(this string val)
        {
            try
            {
                return Convert.ToInt32(val);
            }
            catch
            {
                return 0;
            }
        }

        public static int TryTrunInt32(this string val)
        {
            try
            {
                return Convert.ToInt32(Regex.Match(val, @"\d+").Value);
            }
            catch
            {
                return 0;
            }
        }

        //public static T DeepCopy<T>(this T obj)
        //{
        //    try
        //    {
        //        var json = JsonConvert.SerializeObject(obj);
        //        return JsonConvert.DeserializeObject<T>(json);
        //    }
        //    catch
        //    {
        //        return default;
        //    }
        //}

        public static string ToEncryptCode(this string code, int showLength = 2)
        {
            var codeLength = code.Length;

            if (codeLength - (showLength * 2) > 0)
            {
                return $"{code.Substring(0, showLength)}{new string('*', codeLength - showLength * 2)}{code.Substring(codeLength - showLength, showLength)}";
            }
            else
            {
                return new string('*', codeLength);
            }
        }

        public static T ToObject<T>(this string s)
        {
            T t = default(T);

            //// 移除可能的外层引号
            //string json = s.Trim('"');
            //// 替换可能的转义问题
            //json = json.Replace("\\\"", "\"");
            //// 然后进行解析
            //var result = JsonConvert.DeserializeObject<T>(json);

            try
            {
                t = JsonConvert.DeserializeObject<T>(s);
            }
            catch (Exception ex)
            {
                LoggerService.Error($"数据异常，原数据:{s} \r\n", ex);
                throw ex;
            }
            return t;
        }

        public static object ConvertToObject(this object obj, Type type)
        {
            if (type == null) return obj;
            if (obj == null) return type.IsValueType ? Activator.CreateInstance(type) : null;

            Type underlyingType = Nullable.GetUnderlyingType(type);
            if (type.IsAssignableFrom(obj.GetType())) // 如果待转换对象的类型与目标类型兼容，则无需转换
            {
                return obj;
            }
            else if ((underlyingType ?? type).IsEnum) // 如果待转换的对象的基类型为枚举
            {
                if (underlyingType != null && string.IsNullOrEmpty(obj.ToString())) // 如果目标类型为可空枚举，并且待转换对象为null 则直接返回null值
                {
                    return null;
                }
                else
                {
                    return System.Enum.Parse(underlyingType ?? type, obj.ToString());
                }
            }
            else if (typeof(IConvertible).IsAssignableFrom(underlyingType ?? type)) // 如果目标类型的基类型实现了IConvertible，则直接转换
            {
                try
                {
                    return Convert.ChangeType(obj, underlyingType ?? type, null);
                }
                catch
                {
                    return underlyingType == null ? Activator.CreateInstance(type) : null;
                }
            }
            else
            {
                TypeConverter converter = TypeDescriptor.GetConverter(type);
                if (converter.CanConvertFrom(obj.GetType()))
                {
                    return converter.ConvertFrom(obj);
                }
                ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes);
                if (constructor != null)
                {
                    object o = constructor.Invoke(null);
                    PropertyInfo[] propertys = type.GetProperties();
                    Type oldType = obj.GetType();
                    foreach (PropertyInfo property in propertys)
                    {
                        PropertyInfo p = oldType.GetProperty(property.Name);
                        if (property.CanWrite && p != null && p.CanRead)
                        {
                            property.SetValue(o, ConvertToObject(p.GetValue(obj, null), property.PropertyType), null);
                        }
                    }
                    return o;
                }
            }
            return obj;
        }

        public static string ToJson(this object obj, string[] IgnoreParams = null)
        {
            var settings = new JsonSerializerSettings();
            settings.Converters.Add(new StringEnumConverter());
            if (IgnoreParams?.Length > 0)
            {
                settings.ContractResolver = new DynamicPropertyIgnoringContractResolver(IgnoreParams);
            }
            //settings.ContractResolver = new DynamicPropertyIgnoringContractResolver(new[] { "Children", "Parents" , "ParentKeyValue" });
            settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            return JsonConvert.SerializeObject(obj, Formatting.Indented, settings);
        }

        /// <summary>
        /// string转枚举
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="type"></param>
        /// <returns></returns>
        public static T ToEnum<T>(this string type)
        {
            return (T)System.Enum.Parse(typeof(T), type);
        }

        public static dynamic GetValueFromDynamicPath(string Json, string Path)
        {
            if (string.IsNullOrEmpty(Path))
            {
                return null;
            }
            if (!Json.StartsWith("["))
            {
                return GetObjectValueByDynamicPath(Json, Path);
            }
            JArray jArray = JArray.Parse(Json);
            for (int i = 0; i < jArray.Count; i++)
            {
                JObject Item = jArray[i] as JObject;
                foreach (JProperty item in Item.Properties())
                {
                }
            }

            //JObject jo = JObject.Parse(Json);
            string[] parts = Path.Split('.');

            JToken current = jArray;
            foreach (string part in parts)
            {
                if (current == null)
                    return null;

                if (part.Contains("["))
                {
                    string arrayName = part.Substring(0, part.IndexOf('['));
                    int index = int.Parse(part.Substring(part.IndexOf('[')).Replace("[", "").Replace("]", ""));
                    current = ((JArray)current[arrayName])?[index];
                }
                else
                {
                    current = current[part];
                }
            }

            return current?.ToString();
        }

        public static dynamic GetObjectValueByDynamicPath(string Json, string Path)
        {
            if (string.IsNullOrEmpty(Path))
            {
                return null;
            }
            JObject jo = JObject.Parse(Json);
            string[] parts = Path.Split('.');

            JToken current = jo;
            foreach (string part in parts)
            {
                if (current == null)
                    return null;

               current = current[part];
            }

            return current?.ToString();
        }

        public static T ConvertToType<T>(string input)
        {
            try
            {
                return (T)Convert.ChangeType(input, typeof(T));
            }
            catch (Exception ex)
            {
                Console.WriteLine($"转换出错: {ex.Message}");
                return default(T);
            }
        }

    }
}
